﻿using System;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
using System.Web;

namespace EzNetwork
{
    public class Response
    {
        private WebResponse _WebResponse
        { get; set; }
        public Response(WebResponse _response)
        {
            _WebResponse = _response;
        }
        public string GetHeader(string _headerName)
        {
            return _WebResponse.Headers[_headerName];
        }
        public string GetFullHeader()
        {
            return _WebResponse.Headers.ToString();
        }
        public string CookieHeader()
        {
            return GetHeader("Set-Cookie");
        }
        public string ResponseURI
        {
            get { return _WebResponse.ResponseUri.ToString(); }
        }
        public string ContentType
        {
            get { return _WebResponse.ContentType; }
        }
        public string Source
        { get { return new StreamReader(_WebResponse.GetResponseStream()).ReadToEnd(); } }
    }
    public static class Extensions
    {
        public static string Between(this string input, string firstStr, string secondStr, int startposition = 0)
        {
            int firstIndex = input.IndexOf(firstStr, startposition);
            int secondIndex = input.IndexOf(secondStr, firstIndex + firstStr.Length);
            if (firstIndex != -1 && secondIndex != -1)
            {
                return input.Substring(firstIndex + firstStr.Length, secondIndex - (firstIndex + firstStr.Length));
            }
            return string.Empty;
        }
        public static void WritePostData(this HttpWebRequest req, string postdata)
        {
            var data = Encoding.ASCII.GetBytes(postdata);
            req.ContentLength = data.Length;
            using (Stream writer = req.GetRequestStream())
            {
                writer.Write(data, 0, data.Length);
            }
        }
        public static void WritePostData(this HttpWebRequest req, Dictionary<string,string> postdata)
        {
            string postData = "";
            foreach (var k in postdata)
                postData += k.Key + "=" + k.Value + "&";
            if (postData[postData.Length - 1] == '&')
                postData.Remove(postData.Length - 1);
            var data = Encoding.ASCII.GetBytes(postData);
            req.ContentLength = data.Length;
            using (Stream writer = req.GetRequestStream())
            {
                writer.Write(data, 0, data.Length);
            }
        }
        public static Dictionary<string, string> ParseQueryString(this string query)
        {
            return Regex.Matches(query, "([^?=&]+)(=([^&]*))?").Cast<Match>().ToDictionary(x => x.Groups[1].Value, x => HttpUtility.UrlDecode(x.Groups[3].Value));
        }
        public static Dictionary<string, string> ToDictionary(this NameValueCollection col)
        {
            Dictionary<string, string> dict = new Dictionary<string, string>();
            foreach (var k in col.AllKeys)
                dict.Add(k, col[k]);
            return dict;
        }
        public static string UrlEncode(this string input)
        {
            return HttpUtility.UrlEncode(input);
        }
        public static string HtmlEncode(this string input)
        {
            return HttpUtility.HtmlEncode(input);
        }
    }
    public class PostRequestBuilder
    {
        public Dictionary<string, string> PostData;
        public PostRequestBuilder()
        {
            
        }
        public PostRequestBuilder(string _postData = null)
        {
            PostData = new Dictionary<string, string>();
            if (!string.IsNullOrEmpty(_postData)) PostData = _postData.ParseQueryString();
        }
        public PostRequestBuilder(NameValueCollection _postData = null)
        {
            PostData = new Dictionary<string, string>();
            if (_postData != null) PostData = _postData.ToDictionary();
        }
    }
    public class EzClient
    {
        public static class DefaultHeaders
        {
            public static string UserAgent
            { get; set; }
            public static string Accept
            { get; set; }
            public static string ContentType
            { get; set; }
        }
        public static class Settings
        {
            public static bool UseCookies
            { get; set; }
            public static bool AutoRedirect
            { get; set; }
            public static DecompressionMethods DecompressionMethods = DecompressionMethods.None;
            public static class Cookies
            {
                public static CookieContainer CookieContainer
                { get; set; }
            }
        }
        public EzClient()
        {

        }
        public EzClient(string _userAgent = "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36", bool _autoRedirect = true, CookieContainer _cookieContainer = null)
        {

        }
        public Response Get(string _Url)
        {
            var request = (HttpWebRequest)WebRequest.Create(_Url);
            if (DefaultHeaders.Accept != string.Empty)
                request.Accept = DefaultHeaders.Accept;
            if (DefaultHeaders.ContentType != string.Empty)
                request.ContentType = DefaultHeaders.ContentType;
            request.AllowAutoRedirect = Settings.AutoRedirect;
            request.Method = "GET";
            request.CookieContainer = Settings.UseCookies ? Settings.Cookies.CookieContainer : null;
            request.AutomaticDecompression = Settings.DecompressionMethods;
            return new Response(request.GetResponse());
        }
        public Response Post(string _Url, PostRequestBuilder prb, Dictionary<string, string> AdditionalHeaders,bool useDefaultContentType = false)
        {
            var request = (HttpWebRequest)WebRequest.Create(_Url);
            if (DefaultHeaders.Accept != string.Empty)
                request.Accept = DefaultHeaders.Accept;
            if (DefaultHeaders.ContentType != string.Empty && useDefaultContentType)
                request.ContentType = DefaultHeaders.ContentType;
            else
                request.ContentType = "application/x-www-form-urlencoded";
            if (AdditionalHeaders != null)
                foreach (var header in AdditionalHeaders)
                    request.Headers.Add(header.Key,header.Value);
            request.Method = "POST";
            request.AllowAutoRedirect = Settings.AutoRedirect;
            request.CookieContainer = Settings.UseCookies ? Settings.Cookies.CookieContainer : null;
            request.AutomaticDecompression = Settings.DecompressionMethods;
            request.WritePostData(prb.PostData);
            return new Response(request.GetResponse());
        }
        public Response Post(string _Url, PostRequestBuilder prb, bool useDefaultContentType = false)
        {
            var request = (HttpWebRequest)WebRequest.Create(_Url);
            if (DefaultHeaders.Accept != string.Empty)
                request.Accept = DefaultHeaders.Accept;
            if (DefaultHeaders.ContentType != string.Empty && useDefaultContentType)
                request.ContentType = DefaultHeaders.ContentType;
            else request.ContentType = "application/x-www-form-urlencoded";
            request.AllowAutoRedirect = Settings.AutoRedirect;
            request.Method = "POST";
            request.CookieContainer = Settings.UseCookies ? Settings.Cookies.CookieContainer : null;
            request.AutomaticDecompression = Settings.DecompressionMethods;
            request.WritePostData(prb.PostData);
            return new Response(request.GetResponse());
        }
        public void AddCookie(Cookie c)
        {
            Settings.Cookies.CookieContainer.Add(c);
        }
        public void AddCookie(string name, string value, string path, string domain)
        {
            Settings.Cookies.CookieContainer.Add(new Cookie(name, value, path, domain));
        }
    }
}
